﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Globalization;
using System.IO;

namespace ReToolNaming
{
    public partial class Form1 : Form
    {
        public int indexMatch;
        public List<string> ListColors;
        public Form1()
        {
            InitializeComponent();
            tbSearchPatternLeft.Text = "*.avi";
            tbSearchPatternRight.Text = "*.srt";
            lvFilesLeft.AllowDrop = true;
            lvFilesRight.AllowDrop = true;
            indexMatch = 1;
            ListColors = GetColors();
        }
        protected string GetPathName(string stringPath)
  		{
  			//Get Name of folder
  			string[] stringSplit = stringPath.Split('\\');
  			int _maxIndex = stringSplit.Length;
  			return stringSplit[_maxIndex-1];
  		}

        protected string formatDate(DateTime dtDate)
        {
            //Get date and time in short format
            string stringDate = "";

            stringDate = dtDate.ToShortDateString().ToString() + " " + dtDate.ToShortTimeString().ToString();

            return stringDate;
        }

        protected string formatSize(Int64 lSize)
        {
            //Format number to KB
            string stringSize = "";
            NumberFormatInfo myNfi = new NumberFormatInfo();

            Int64 lKBSize = 0;

            if (lSize < 1024)
            {
                if (lSize == 0)
                {
                    //zero byte
                    stringSize = "0";
                }
                else
                {
                    //less than 1K but not zero byte
                    stringSize = "1";
                }
            }
            else
            {
                //convert to KB
                lKBSize = lSize / 1024;
                //format number with default format
                stringSize = lKBSize.ToString("n", myNfi);
                //remove decimal
                stringSize = stringSize.Replace(".00", "");
            }

            return stringSize + " KB";

        }

  		protected void PopulateFiles(ListView lvFiles, string searchPattern)
  		{
  			//Populate listview with files
  			string[] lvData =  new string[4];
  			
  			//clear list
  			InitListView(lvFiles);

			//check path
			if(Directory.Exists((string) getFullPath()) == false)
			{
				MessageBox.Show("Directory or path does not exist.");
			}
			else
			{
				try
				{
                    string[] stringFiles = Directory.GetFiles(getFullPath(), searchPattern, SearchOption.TopDirectoryOnly);
					string stringFileName = "";
					DateTime dtModifyDate;
					Int64 lFileSize = 0;

					//loop throught all files
					foreach (string stringFile in stringFiles)
					{
						stringFileName = stringFile;
						FileInfo objFileSize = new FileInfo(stringFileName);
						lFileSize = objFileSize.Length;
						dtModifyDate = objFileSize.LastWriteTime; //GetLastWriteTime(stringFileName);

						//create listview data
						lvData[0] = GetPathName(stringFileName);
						lvData[1] = formatSize(lFileSize);
						
						//check if file is in local current day light saving time
						if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(dtModifyDate) == false)
						{
							//not in day light saving time adjust time
							lvData[2] = formatDate(dtModifyDate.AddHours(1));
						}
						else							
						{
							//not in day light saving time adjust time
							lvData[2] = formatDate(dtModifyDate);
						}

                        //Create actual list item
						ListViewItem lvItem = new ListViewItem(lvData,0);
                        lvFiles.Items.Add(lvItem);

						
					}
				}
				catch (IOException e)
				{
					MessageBox.Show("Error: Drive not ready or directory does not exist.");
				}
				catch (UnauthorizedAccessException e)
				{
					MessageBox.Show("Error: Drive or directory access denided.");
				}
				catch (Exception e)
				{
					MessageBox.Show("Error: " + e);
				}
			}
  			
  		}
  
  		protected string getFullPath()
  		{
            if (folderBrowserDialog1.SelectedPath.ToString() == "")
                return Directory.GetCurrentDirectory();
            else return folderBrowserDialog1.SelectedPath.ToString();
  		}
        
        protected void InitListView(ListView lvFiles)
  		{
  			//init ListView control
  			lvFiles.Clear();		//clear control
  			//create column header for ListView
            lvFiles.Columns.Add("Name", 400);
            lvFiles.Columns.Add("Size", 100);
            lvFiles.Columns.Add("Modified", 100);
            lvFiles.Columns.Add("Matching", 50);
  
  		}

        private void Form1_Load(object sender, EventArgs e)
        {
            PopulateFiles(lvFilesLeft, tbSearchPatternLeft.Text);
            PopulateFiles(lvFilesRight, tbSearchPatternRight.Text);
        }

        private void bFilterLeft_Click(object sender, EventArgs e)
        {
            PopulateFiles(lvFilesLeft, tbSearchPatternLeft.Text);
        }

        private void bFilterRight_Click(object sender, EventArgs e)
        {
            PopulateFiles(lvFilesRight, tbSearchPatternRight.Text);
        }

        private List<string> GetColors()
        {
            //create a generic list of strings
            List<string> colors = new List<string>();
            //get the color names from the Known color enum
            string[] colorNames = Enum.GetNames(typeof(KnownColor));
            //iterate thru each string in the colorNames array
            foreach (string colorName in colorNames)
            {
                //cast the colorName into a KnownColor
                KnownColor knownColor = (KnownColor)Enum.Parse(typeof(KnownColor), colorName);
                //check if the knownColor variable is a System color
                if (knownColor > KnownColor.Transparent)
                {
                    //add it to our list
                    if (colorName != "Black" && colorName != "White") colors.Add(colorName);
                }
            }
            //return the color list
            return colors;
        }

        private void bMatch_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(lvFilesLeft.SelectedItems.Count.ToString());
            if (lvFilesLeft.CheckedItems.Count > 0 && lvFilesRight.CheckedItems.Count > 0)
            {
                MatchRow(lvFilesLeft);
                MatchRow(lvFilesRight);
                indexMatch++;
            }
            else
            {
                MessageBox.Show("Matching not done. Chech in both sides a file.");
            }
        }

        private void MatchRow(ListView lvFiles)
        {
                foreach (ListViewItem lvItem in lvFiles.Items)
                {
                    if (lvItem.Checked)
                    {
                        lvItem.SubItems[3].Text = indexMatch.ToString();
                        lvItem.BackColor = Color.FromName(ListColors[indexMatch%ListColors.Count()]);
                        lvItem.Checked = false;
                        break;
                    }
                }
        }

        public void Rename(string strDirection)
        {
            if (MessageBox.Show("Please be sure you have selected the right matching and right renaming direction cause this operation is ireversible.", "Warrning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
            {
                foreach (ListViewItem lvItemLeft in lvFilesLeft.Items)
                {
                    foreach (ListViewItem lvItemRight in lvFilesRight.Items)
                    {
                        if (lvItemLeft.SubItems[3].Text == lvItemRight.SubItems[3].Text && lvItemLeft.SubItems[3].Text.Length > 0)
                        {
                            FileInfo fileInfoLeft = new FileInfo(getFullPath() + "\\" + lvItemLeft.Text);
                            string strLeftFileNameOnly = fileInfoLeft.Name;
                            strLeftFileNameOnly = strLeftFileNameOnly.Replace(fileInfoLeft.Extension.ToString(), "");

                            FileInfo fileInfoRight = new FileInfo(getFullPath() + "\\" + lvItemRight.Text);
                            string strRightFileNameOnly = fileInfoRight.Name;
                            strRightFileNameOnly = strRightFileNameOnly.Replace(fileInfoRight.Extension.ToString(), "");

                            if (strDirection == "left")
                            {
                                File.Move(fileInfoRight.FullName, fileInfoRight.Directory.FullName + "\\" + strLeftFileNameOnly + fileInfoRight.Extension);
                                lvItemLeft.SubItems[3].Text = "";
                                lvItemRight.SubItems[3].Text = "";
                            }
                            else
                            {
                                File.Move(fileInfoLeft.FullName, fileInfoLeft.Directory.FullName + "\\" + strRightFileNameOnly + fileInfoLeft.Extension);
                                lvItemLeft.SubItems[3].Text = "";
                                lvItemRight.SubItems[3].Text = "";
                            }
                        }
                    }
                }
                PopulateFiles(lvFilesLeft, tbSearchPatternLeft.Text);
                PopulateFiles(lvFilesRight, tbSearchPatternRight.Text);
            }
        }

        private void bRenameFromLeft_Click(object sender, EventArgs e)
        {
            Rename("left");
        }

        private void bRenameFromRight_Click(object sender, EventArgs e)
        {
            Rename("right");
        }

        private void lvFilesLeft_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
                bMatch.PerformClick();

        }

        private static string ExtractNumbers(string expr, string strComplexRegex)
        {
            if (String.Empty == strComplexRegex)
                return string.Join(null, System.Text.RegularExpressions.Regex.Split(expr, "[^\\d$]"));
            else
                return System.Text.RegularExpressions.Regex.Match(expr, strComplexRegex).Value.ToString();
        }

        private void bAutoDetect_Click(object sender, EventArgs e)
        {
            bClearMatching.PerformClick();
            lvFilesLeft.Invalidate();
            lvFilesRight.Invalidate();
            pbProgres.Show();
            pbProgres.Value = 0;
            foreach (ListViewItem lvItem in lvFilesLeft.Items)
            {
                if (lvItem.SubItems[3].Text != string.Empty) continue;
                
                string strLeftFileName = lvItem.Text;
                string strKeyNumberLeft = ExtractNumbers(strLeftFileName, cbUseComplexRegex.Checked ? tbRegex.Text.ToString() : String.Empty);

                foreach (ListViewItem lvRightItem in lvFilesRight.Items)
                {
                    if (lvRightItem.SubItems[3].Text != string.Empty) continue;

                    string strRightFileName = lvRightItem.Text;
                    string strKeyNumberRight = ExtractNumbers(strRightFileName, cbUseComplexRegex.Checked ? tbRegex.Text.ToString() : String.Empty);
                    
                    if (cbUseComplexRegex.Checked)
                    {
                        strKeyNumberLeft = ExtractNumbers(strKeyNumberLeft, string.Empty);
                        strKeyNumberRight = ExtractNumbers(strKeyNumberRight, string.Empty);
                    }

                    //MessageBox.Show((strLeftFileName) + " - " + strKeyNumberLeft + " -=- " + strRightFileName + " - " + strKeyNumberRight);

                    if (strKeyNumberLeft.Contains(strKeyNumberRight) || strKeyNumberRight.Contains(strKeyNumberLeft))
                    {
                        lvItem.Checked = true;
                        lvRightItem.Checked = true;
                        bMatch.PerformClick();
                        if (!cbSpeed.Checked)
                        {
                            lvFilesLeft.Refresh();//for special effect.
                            lvFilesRight.Refresh();
                        }
                        break;
                    }
                }
                pbProgres.Value = (int)((decimal)(lvItem.Index+1.00) * (decimal)(100.00 / lvFilesLeft.Items.Count));
            }
            pbProgres.Hide();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();
            PopulateFiles(lvFilesLeft, tbSearchPatternLeft.Text);
            PopulateFiles(lvFilesRight, tbSearchPatternRight.Text);

        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutBox = new AboutBox1();
            aboutBox.ShowDialog();
            aboutBox.Dispose();
        }

        private void cbUseComplexRegex_CheckedChanged(object sender, EventArgs e)
        {
            tbRegex.Enabled = cbUseComplexRegex.Checked;
        }

        private void button1_Click(object sender, EventArgs e)//Clear matches.
        {
            foreach (ListViewItem lvLeftItem in lvFilesLeft.Items)
            {
                lvLeftItem.SubItems[3].Text = string.Empty;
                lvLeftItem.BackColor = Color.White;
            }
            foreach (ListViewItem lvRightItem in lvFilesRight.Items)
            {
                lvRightItem.SubItems[3].Text = string.Empty;
                lvRightItem.BackColor = Color.White;
            }
        }

        private void BehaveLikeRadioCheckBox(ListView lvFiles, ListViewItem checkedListVieeItem)
        {
            bool checkedState = checkedListVieeItem.Checked;
            foreach (ListViewItem lvItem in lvFiles.CheckedItems)
            {
                lvItem.Checked = false;
            }
            checkedListVieeItem.Checked = checkedState;
        }

        private void lvFilesLeft_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            BehaveLikeRadioCheckBox(lvFilesLeft, e.Item);
        }

        private void lvFilesRight_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            BehaveLikeRadioCheckBox(lvFilesRight, e.Item);
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

            foreach (string file in files)
            {
                bool flagPass = false;
                if (Directory.Exists(file.ToString()))
                {
                    folderBrowserDialog1.SelectedPath = file.ToString();
                    flagPass = true;
                }
                if (File.Exists(file.ToString()))
                {
                    FileInfo ddFile = new FileInfo(file.ToString());
                    folderBrowserDialog1.SelectedPath = ddFile.Directory.FullName.ToString();
                    flagPass = true;
                }
                if (flagPass)
                {
                    PopulateFiles(lvFilesLeft, tbSearchPatternLeft.Text);
                    PopulateFiles(lvFilesRight, tbSearchPatternRight.Text);
                    break;
                }
            }
            
        }

        private void Form1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            {
                e.Effect = DragDropEffects.All;
            }  
        }

    }
}
